/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_kernel.htm
 *
 * Zhiqim Kernel is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.kernel.model.codes;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import org.zhiqim.kernel.constants.CodeConstants;

/**
 * HMAC算法<br><br>
 * 1.注意编码类型支持HmacMD5 | HmacSHA1 | HmacSHA256 | HmacSHA384 | HmacSHA512<br>
 * 2.对结果支持Base64进行编译成字符串，如果要HEX,MD5使用通用的signature得到byte[]后处理<br>
 *
 * @version v1.0.0 @author zouzhigang 2014-2-27 新建与整理
 */
public class HMAC implements CodeConstants
{
    /**
     * 生成签名数据，通常用于对数据的验证（防篡改）
     * 
     * @param data                          待加密的数据
     * @param key                           加密使用的key
     * @param keyCoding                     加密算法 HmacMD5 | HmacSHA1 | HmacSHA256 | HmacSHA384 | HmacSHA512
     * @return                              生成签名值
     * @throws InvalidKeyException          非法的KEY异常
     * @throws NoSuchAlgorithmException     不支持的算法异常
     */
    public static byte[] signature(byte[] data, byte[] key, String keyCoding) throws InvalidKeyException, NoSuchAlgorithmException
    {
        SecretKeySpec secretKey = new SecretKeySpec(key, keyCoding);
        Mac mac = Mac.getInstance(secretKey.getAlgorithm());
        mac.init(secretKey);
        return mac.doFinal(data);
    }
    
    /*************************************************************************************************/
    //提供的常用签名方法
    /*************************************************************************************************/
    
    /** 生成签名数据，指定UTF-8和SHA256编码，HmacSHA256(UTF-8) */
    public static byte[] signatureUTF8_SHA256(String data, String key) throws InvalidKeyException, NoSuchAlgorithmException
    {
        return signature(data.getBytes(_UTF_8_C_), key.getBytes(_UTF_8_C_), _HMAC_SHA256_);
    }
    
    /** 生成签名数据，指定UTF-8和SHA256编码，以及对结果进行Base64编码，Base64(HmacSHA256(UTF-8)) */
    public static String signatureUTF8_SHA256_BASE64(String data, String key) throws InvalidKeyException, NoSuchAlgorithmException
    {
        return new String(Base64Encoder.encode(signature(data.getBytes(_UTF_8_C_), key.getBytes(_UTF_8_C_), _HMAC_SHA256_)), _UTF_8_C_);
    }
    
    /** 生成签名数据，指定UTF-8和SHA1编码，HmacSHA1(UTF-8) */
    public static byte[] signatureUTF8_SHA1(String data, String key) throws InvalidKeyException, NoSuchAlgorithmException
    {
        return signature(data.getBytes(_UTF_8_C_), key.getBytes(_UTF_8_C_), _HMAC_SHA1_);
    }
    
    /** 生成签名数据，指定UTF-8和SHA1编码，以及对结果进行Base64编码，Base64(HmacSHA1(UTF-8)) */
    public static String signatureUTF8_SHA1_BASE64(String data, String key) throws InvalidKeyException, NoSuchAlgorithmException
    {
        return new String(Base64Encoder.encode(signature(data.getBytes(_UTF_8_C_), key.getBytes(_UTF_8_C_), _HMAC_SHA1_)), _UTF_8_C_);
    }
}
